﻿#region

using System;
using System.Collections.Generic;
using EsbMonitorExtension.Infrastructure;
using EsbMonitorExtension.MonitorTasks.Base;
using EsbMonitorMessages.Domain;
using EsbMonitorMessages.Events;
using log4net;
using NServiceBus;
using NServiceBus.Unicast;
using NServiceBus.Utils;

#endregion

namespace EsbMonitorExtension.MonitorTasks
{
    public class PublisherStartedTask : BaseMonitorTask
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof (PublisherStartedTask));

        private readonly ITypesFinder _typesFinder;

        public PublisherStartedTask(IUnicastBus bus, ITypesFinder typesFinder)
            : base(bus)
        {
            _typesFinder = typesFinder;
        }

        public override void RunTask()
        {
            if (!IsPublisherEndpointPresent())
            {
                Logger.Info("No Publisher Endpoint");
                return;
            }

            Logger.Info("Running PublisherStartedTask");

            ServiceInfo thisServiceInfo = Bus.ServiceInfo();

            RaisePublisherStartedEvent(thisServiceInfo);

            Bus.ClientSubscribed +=
                (sender, e) =>
                    {
                        Type type = Type.GetType(e.MessageType);
                        String subscriberAddress = e.SubscriberAddress;
                        String subscriberFullAddress = MsmqUtilities.GetFullPathWithoutPrefix(subscriberAddress);
                        OnClientSubscribed(thisServiceInfo, new InputQueueInfo(subscriberFullAddress), new TypeInfo(type));
                    };

            Logger.Info("Finished PublisherStartedTask");
        }


        private void RaisePublisherStartedEvent(ServiceInfo thisServiceInfo)
        {
            Bus.Send<IPublisherStarted>(m =>
                                            {
                                                m.ServiceInfo = thisServiceInfo;
                                                m.EventTime = DateTime.Now;
                                            });
        }

        private bool IsPublisherEndpointPresent()
        {
            IEnumerable<Type> endpoints = _typesFinder.ScanAssembliesFor<IConfigureThisEndpoint>();
            foreach (Type endpoint in endpoints)
            {
                if (typeof (AsA_Publisher).IsAssignableFrom(endpoint))
                {
                    return true;
                }
            }

            return false;
        }

        private void OnClientSubscribed(ServiceInfo publisherServiceInfo, InputQueueInfo subscriberInputQueue, TypeInfo typeInfo)
        {
            Bus.Send<ISubscriptionRegistered>(m =>
                                                  {
                                                      m.PublisherInfo = publisherServiceInfo;
                                                      m.SubscriberInputQueue = subscriberInputQueue;
                                                      m.TypeName = typeInfo;
                                                      m.EventTime = DateTime.Now;
                                                  });
        }
    }
}